home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 135 (1990-05-15)(Ossowski, Stefan)(DE)(PD)[v Disaster Master 2].zip / Taifun 135 (1990-05-15)(Ossowski, Stefan)(DE)(PD)[v Disaster Master 2].adf / TurboMandel / source / TurboIFF.c < prev    next >
C/C++ Source or Header  |  1990-02-23  |  9KB  |  320 lines

  1. /**************
  2. * TURBOMANDEL *
  3. **************/
  4.  
  5. /* IFF read/write */
  6.  
  7. #include <stdio.h>
  8. #include <exec/types.h>
  9. #include <exec/memory.h>
  10. #include <graphics/gfx.h>
  11. #include <intuition/intuition.h>
  12. #include <libraries/dos.h>
  13.  
  14. struct iff_chunk { long iff_type, iff_length; };
  15. struct form_chunk { long fc_type, fc_length, fc_subtype; };
  16.  
  17. struct BitMapHeader {
  18.    UWORD w, h, x, y;
  19.    UBYTE nPlanes, masking, compression, pad1;
  20.    UWORD transparentColor;
  21.    UBYTE xAspect, yAspect;
  22.    WORD pageWidth, pageHeight;
  23.    };
  24. struct ILBM_info {
  25.    struct BitMapHeader header;
  26.    struct BitMap bitmap;
  27.    UBYTE cmap[96];
  28.    };
  29. extern struct MandelChunk {
  30.    ULONG XCoo[2], YCoo[2], XSide[2], YSide[2];
  31.    UWORD Iteration;
  32.    UBYTE Calculation, Flags;
  33.    SHORT TopPos[3], DecrStep[3], ColInt[3];
  34.    } MandChunk;
  35.  
  36. read_iff (info, name, just_header)
  37. struct ILBM_info *info;
  38. char *name;
  39. int just_header;
  40. {
  41.    UBYTE bool;
  42.    FILE *file;
  43.    struct form_chunk chunk;
  44.  
  45.    if ((file = fopen (name, "r") ) == 0) return (FALSE);
  46.    if (fread (&chunk, sizeof (struct form_chunk), 1, file) != 1) {
  47.       fclose (file); return (FALSE);
  48.       }
  49.    if (chunk.fc_type != 'FORM' || chunk.fc_subtype != 'ILBM') {
  50.       fclose (file); return (FALSE);
  51.       }
  52.    bool = read_ilbm (file, info, chunk.fc_length - sizeof (chunk), just_header);
  53.    fclose (file);
  54.    return ((int)bool);
  55. }
  56.  
  57. read_ilbm (file, info, length, just_header)
  58. FILE *file;
  59. struct ILBM_info *info;
  60. long length;
  61. int just_header;
  62. {
  63.    struct iff_chunk chunk;
  64.    long read_in = 0;
  65.    int got_header = FALSE, got_cmap = FALSE;
  66.  
  67.    while (read_in < length) {
  68.       if (fread (&chunk, sizeof (chunk), 1, file) != 1) return (FALSE);
  69.       switch (chunk.iff_type) {
  70.          case 'BMHD':
  71.             if (fread (&info->header, sizeof(info->header), 1, file) != 1)
  72.                return (FALSE);
  73.             got_header = TRUE;
  74.             break;
  75.          case 'MANC':      /* read mandel chunk */
  76.             if (fread (&MandChunk, sizeof(MandChunk), 1, file) != 1)
  77.                return (FALSE);
  78.             break;
  79.          case 'CMAP':
  80.             if (!got_header) return (FALSE);
  81.             if (chunk.iff_length <= 96) {
  82.                if (fread (info->cmap, (int)chunk.iff_length, 1, file) != 1)
  83.                   return (FALSE);
  84.                }
  85.             else {
  86.                if (fread(info->cmap, 96, 1, file) != 1) return (FALSE);
  87.                fseek (file, (long)chunk.iff_length - sizeof (3 * 32), 1);
  88.                }
  89.             got_cmap = TRUE;
  90.             break;
  91.          case 'BODY':
  92.             if (!got_cmap || !got_header) return (FALSE);
  93.             if (just_header) return (TRUE);
  94.             return (read_body (file, info, chunk.iff_length));
  95.          default:
  96.             fseek (file, (long)chunk.iff_length, 1);
  97.             break;
  98.          }
  99.       read_in += chunk.iff_length + sizeof(chunk);
  100.       }
  101.    return (FALSE); 
  102. }
  103.  
  104. read_body (file, info, length)
  105. FILE *file;
  106. register struct ILBM_info *info;
  107. long length;
  108. {
  109.    long i, j, plane_offset;
  110.  
  111.    if (info->header.compression != 0 && info->header.compression != 1)
  112.       return (FALSE);
  113.  
  114.    plane_offset = 0;
  115.    for (i = 0; i < info->bitmap.Rows; i++) {
  116.       if (info->header.compression == 0) {
  117.          for (j = 0; j < info->bitmap.Depth; j++)
  118.             if (fread(info->bitmap.Planes[j] + plane_offset,
  119.                info->bitmap.BytesPerRow, 1, file) != 1) return(FALSE);
  120.          }
  121.       else {
  122.          register char *dest, value;
  123.          register int so_far, count;
  124.  
  125.          for (j = 0; j < info->bitmap.Depth; j++) {
  126.             so_far = info->bitmap.BytesPerRow;
  127.             dest = (char *)info->bitmap.Planes[j] + plane_offset;
  128.             while (so_far > 0) {
  129.                value = getc (file);
  130.                if (value > 0 && value != 128) {
  131.                   count = (int)value + 1;
  132.                   so_far -= count;
  133.                   if (fread (dest, count, 1, file) != 1) return (FALSE);
  134.                   dest += count;
  135.                   }
  136.                else {
  137.                   count = (int)-value + 1;
  138.                   so_far -= count;
  139.                   value = getc (file);
  140.                   while (--count >= 0) *dest++ = value;
  141.                   }
  142.                }
  143.             if (so_far != 0) return (FALSE);
  144.             }
  145.          }
  146.       plane_offset += info->bitmap.BytesPerRow;
  147.       }
  148.    return (TRUE);
  149. }
  150.  
  151. #define DUMP   0
  152. #define RUN    1
  153.  
  154. ULONG pack_row (source, dest, size)
  155. char *source, *dest;
  156. int size;
  157. {
  158.    char c, lastc = 0, *olddest;
  159.    short mode = DUMP, nbuf = 0, rstart = 0, i;
  160.    char buf[128*3/2];
  161.  
  162.    olddest = dest;
  163.    buf[0] = lastc = *source++;
  164.    nbuf = 1; size--;
  165.    for (; size; --size) {
  166.       buf[nbuf++] = c = *source++;
  167.       if (mode == DUMP) {
  168.          if (nbuf > 128) {
  169.             *dest++ = nbuf - 2;
  170.             for (i = 0; i < nbuf-1; i++) *dest++ = buf[i];
  171.             buf[0] = c; nbuf = 1; rstart = 0;
  172.             }
  173.          else if (c == lastc) {
  174.             if (nbuf - rstart >= 3) {
  175.                if (rstart > 0) {
  176.                   *dest++ = rstart - 1;
  177.                   for (i = 0; i < rstart; i++) *dest++ = buf[i];
  178.                   }
  179.                mode = RUN;
  180.                }
  181.             else if (rstart == 0) mode = RUN;
  182.             }
  183.          else rstart = nbuf - 1;
  184.          }
  185.       else {
  186.          if ((c != lastc) || (nbuf - rstart > 128)) {
  187.             *dest++ = - (nbuf - rstart - 2); *dest++ = lastc;
  188.             buf[0] = c; nbuf = 1; rstart = 0; mode = DUMP;
  189.             }
  190.          }
  191.       lastc = c;
  192.       }
  193.    if (mode == DUMP) {
  194.       *dest++ = nbuf - 1;
  195.       for (i = 0; i < nbuf; i++) *dest++ = buf[i];
  196.       }
  197.    else {
  198.       *dest++ = - nbuf + rstart + 1; *dest++ = lastc;
  199.       }
  200.    return ((ULONG)(dest - olddest));
  201. }
  202.  
  203. ULONG pack_bitmap (file, bm)
  204. FILE *file;
  205. struct BitMap *bm;
  206. {
  207.    char packbuffer[256];
  208.    int i, j, row_length;
  209.    ULONG compressed_length = 0, plane_offset = 0;
  210.  
  211.    for (i = 0; i < bm->Rows; i++) {
  212.       for (j = 0; j < bm->Depth; j++) {
  213.          row_length = pack_row
  214.             (bm->Planes[j] + plane_offset, packbuffer, bm->BytesPerRow);
  215.          if (file) if (fwrite(packbuffer, row_length, 1, file) != 1) return (0);
  216.          compressed_length += row_length;
  217.          }
  218.       plane_offset += bm->BytesPerRow;
  219.       }
  220.    if (compressed_length & 1) {
  221.       if (file) if (putc (0, file) == EOF) return(0);
  222.       compressed_length++;
  223.       }
  224.    return (compressed_length);
  225. }
  226.  
  227. int write_iff (name, colors, scr, compressed)
  228. char *name;
  229. UWORD *colors;
  230. struct Screen *scr;
  231. int compressed;
  232. {
  233.    struct BitMap *bits;
  234.    struct form_chunk chunk;
  235.    struct iff_chunk ichunk;
  236.    struct BitMapHeader header;
  237.    UBYTE rgbcolors[96];
  238.    SHORT i, numcols, j, row_offset;
  239.    ULONG bits_size, viewmodes;
  240.    FILE *file;
  241.  
  242.    if ((file = fopen (name, "w") ) == 0) return(0);
  243.    if (scr) {
  244.       bits = &scr->BitMap;
  245.       if ((numcols = (1 << bits->Depth)) > 32) numcols = 32;
  246.       }
  247.    else numcols = 32;
  248.    chunk.fc_type = 'FORM'; chunk.fc_subtype = 'ILBM';
  249.    chunk.fc_length = 4 + 3 * sizeof (struct iff_chunk) + 12 + 62 +
  250.       numcols * 3 + sizeof(struct BitMapHeader);
  251.    if (scr) {
  252.       if (compressed) {
  253.          if ((bits_size = pack_bitmap (NULL, bits)) == 0) return(0);
  254.          }
  255.       else bits_size = bits->BytesPerRow * bits->Rows * bits->Depth;
  256.       chunk.fc_length += bits_size;
  257.       }
  258.    if (fwrite (&chunk, sizeof(chunk), 1, file) != 1) return(0);
  259.  
  260.    ichunk.iff_type = 'BMHD';
  261.    ichunk.iff_length = sizeof(header);
  262.    if (fwrite (&ichunk, sizeof(ichunk), 1, file) != 1) return(0);
  263.  
  264.    header.masking = header.pad1 = header.transparentColor = 0;
  265.    header.compression = compressed;
  266.    header.pageWidth = bits->BytesPerRow * 8;
  267.    header.pageHeight = bits->Rows;
  268.    header.xAspect = header.yAspect = 10;
  269.  
  270.    /* write bitmapheader */
  271.    if (scr) {
  272.       header.w = bits->BytesPerRow * 8;
  273.       header.h = bits->Rows;
  274.       header.nPlanes = bits->Depth;
  275.       header.x = header.y = 0;
  276.       }
  277.    if (fwrite (&header, sizeof(header), 1, file) != 1) return(0);
  278.  
  279.    /* write camg */
  280.    ichunk.iff_type = 'CAMG'; ichunk.iff_length = 4;
  281.    if (fwrite (&ichunk, sizeof(ichunk), 1, file) != 1) return(0);
  282.    viewmodes = (ULONG)scr->ViewPort.Modes;
  283.    if (fwrite (&viewmodes, 4, 1, file) != 1) return(0);
  284.  
  285.    /* write cmap */
  286.    ichunk.iff_type = 'CMAP'; ichunk.iff_length = numcols * 3;
  287.    if (fwrite (&ichunk, sizeof(ichunk), 1, file) != 1) return(0);
  288.    for (i = 0; i < numcols; i++) {
  289.       rgbcolors[3 * i] = (colors[i] & 0xf00) >> 4;
  290.       rgbcolors[3 * i + 1] = (colors[i] & 0x0f0);
  291.       rgbcolors[3 * i + 2] = (colors[i] & 0x00f) << 4;
  292.       }
  293.    if (fwrite (&rgbcolors[0], numcols * 3, 1, file) != 1) return(0);
  294.  
  295.    /* write mandel chunk */
  296.    ichunk.iff_type = 'MANC'; ichunk.iff_length = sizeof(MandChunk);
  297.    if (fwrite (&ichunk, sizeof(ichunk), 1, file) != 1) return(0);
  298.    if (fwrite (&MandChunk, sizeof(MandChunk), 1, file) != 1) return (0);
  299.  
  300.    if (scr) {
  301.       ichunk.iff_type = 'BODY'; ichunk.iff_length = bits_size;
  302.       if (fwrite(&ichunk, sizeof(ichunk), 1, file) != 1) return(0);
  303.       if (compressed) {
  304.          if (pack_bitmap(file, bits) == 0) return(0);
  305.          }
  306.       else {
  307.          i = bits->Rows;
  308.          row_offset = 0;
  309.          while (--i >= 0) {
  310.             for (j = 0; j < bits->Depth; j++)
  311.                if (fwrite( bits->Planes[j]+row_offset, bits->BytesPerRow,
  312.                   1, file) != 1) return(0);
  313.             row_offset += bits->BytesPerRow;
  314.             }
  315.          }
  316.       }
  317.    fclose (file);
  318.    return (1);
  319. }
  320.